var web = web || {};
web.Draggable = Class.create(); 
web.Draggable.prototype = {
	initialize: function(drag_id, settings) {
		var _this = this;
		this.drag = $('#'+ drag_id);
		if( 0 == this.drag.size()) return;
		this.dragElemSize = {w:this.drag.width(), h:this.drag.height()};
		
		this.lastElemPos = {x:0,y:0};
		this.settings = $.extend({
			handle: this.drag,
			axis: '',
			containment:{x1:0,y1:0,x2:0,y2:0},
			callback: {init:function(){}, move:function(){},stop:function(){}}
		}, settings);
		this.constrainElem = false;
		
		if(typeof this.settings.handle == 'string') {
			this.settings.handle = $('#'+ this.settings.handle);
			if( 0 == this.settings.handle.size() ) this.settings.handle = this.drag;
		}
		
		if( (this.settings.axis.length!=1) || !(/x|y/.test(this.settings.axis)) ) this.settings.axis = '';
		if(typeof this.settings.containment == 'string') {
			var e = $('#'+ this.settings.containment);
			if( 0 == e.size() ) {
				this.settings.containment ={x1:0,y1:0,x2:0,y2:0};
			} else {
				var offset = e.offset();
				this.settings.containment ={
					x1:offset.left,
					y1:offset.top,
					x2:offset.left+e.width(),
					y2:offset.top+e.height()
				};
			}
		}
		
		if( this.settings.containment.x1 > 0 || this.settings.containment.y1 > 0 || this.settings.containment.x2 > 0 || this.settings.containment.y2 > 0 )
			this.constrainElem = true;
		
		if(typeof this.settings.callback.init != 'function') this.settings.callback.init = function(){};
		if(typeof this.settings.callback.move != 'function') this.settings.callback.move = function(){};
		if(typeof this.settings.callback.stop != 'function') this.settings.callback.stop = function(){};
		
		this.settings.handle.css('cursor', 'move');
		this.settings.handle.mousedown(function(e) {
			_this._getElementOffset(e);
			_this.dragInit();
		});
	},
	dragInit: function() {
		var _this = this;
		$(document).bind({
			mousemove: function(e){_this.dragMove(e);},
			mouseup: function(e){_this.dragStop(e);}
		});
		this.settings.callback.init(this);
	},
	dragMove: function(e) {
		var pos = this._getMousePosition(e);
		window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
		
		var x = pos.x - this.lastElemPos.x;
		var y = pos.y - this.lastElemPos.y;
		if( x <= 0 ) x = 0;
		if( y <= 0 ) y = 0;
		
		if( this.settings.axis != '' ) {
			if( this.settings.axis == 'x' ) x = 0;
			else if( this.settings.axis == 'y' ) y = 0;
		}
		
		if( this.constrainElem ) {
			var area = this.settings.containment;
			
			if( x>0 && x<area.x1 ) x = area.x1;
			if( y>0 && y<area.y1 ) y = area.y1;
			
			if( x>0 && ((x+this.dragElemSize.w) > area.x2) ) x = area.x2-this.dragElemSize.w;
			if( y>0 && ((y+this.dragElemSize.h) > area.y2) ) y = area.y2-this.dragElemSize.h;
		}
		
		this.settings.callback.move(this);
		if( x == 0 && y == 0 ) return;
		pos = {left:x, top:y};
		if( x == 0 ) pos = {top:y};
		if( y == 0 ) pos = {left:x};
		
		this.drag.css(pos);		
	},
	dragStop: function(e) {
		$(document).unbind('mousemove').unbind('mouseup');
		this.settings.callback.stop(this);
	},
	_getElementOffset: function(e) {
		var pos = this._getMousePosition(e);
		var offset = this.drag.offset();
		this.lastElemPos = {
			x: pos.x - offset.left,
			y: pos.y - offset.top
		};
	},
	_getMousePosition: function(e) {
		var _event = e || window.event;
		var posx=0,posy=0;
		if ( _event.pageX || _event.pageY ) {
			posx = _event.pageX;
			posy = _event.pageY;
		} else if ( _event.clientX || _event.clientY ) {
			posx = _event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
			posy = _event.clientY + document.body.scrollTop  + document.documentElement.scrollTop;
		}
		return {x: posx, y: posy};
	},
	debug: function(str) {
		$('#span_debug').html(str);
	}
}